import {Component, Input, OnInit} from '@angular/core';
import {
  FormGroup,
  FormBuilder,
  Validators,
  FormControl,
  ValidationErrors
} from '@angular/forms';
import {NzMessageService} from 'ng-zorro-antd';
import {Observable, of, Observer, Subject} from 'rxjs';
import {debounceTime, distinctUntilChanged, switchMap} from 'rxjs/operators';

import {RegConstant} from '@core/constant';
import {User} from '../model/user';
import {I18NService} from '@core/i18n/i18n.service';
import {PopupRes} from '@shared/popup/popup.interface';
import {BaseComponent} from '@shared/base/base.component';
import {UserService} from '../service/user.service';
import {RoleService} from '../../roles/service/role.service';
import {comparisonValue, hasProperty, normObject} from '@shared/utils/data.utils';
import {Debugger} from "inspector";

@Component({
  selector: 'user-modify',
  templateUrl: './user-modify.html'
})

export class UserModifyComponent extends BaseComponent implements OnInit, PopupRes {

  _id: number;

  @Input()
  set id(val: number) {
    this._id = val;
  }

  validateForm: FormGroup;
  /**
   * 角色key:value数据
   */
  rolesOptions = [];

  tempItem: User = new User();

  isCheck = true;

  page = {
    pageNo: 1,
    pageSize: 999
  };

  private accountText = new Subject<any>();

  constructor(
    private fb: FormBuilder,
    private message: NzMessageService,
    private i18nService: I18NService,
    private userService: UserService,
    private roleService: RoleService
  ) {
    super();
    this.validateForm = this.fb.group({
      account: [null, [Validators.required], [this.userNameAsyncValidator]],
      password: [null, [this.passwordValidator]],
      gender: [0, [Validators.required]],
      status: [1, [Validators.required]],
      roles: [null, [Validators.required]],
      phone: [null, [this.phoneValidator]],
      email: [null, [this.emailValidator]],
    });
  }

  ngOnInit(): void {
    if (this._id !== undefined) {
      this.getUser(this._id);
    }
    this.getAllRoles();
    this.initValid();
  }

  initValid(): void {
    this.accountText.pipe(
      // 请求防抖
      debounceTime(500),
      distinctUntilChanged(),
      switchMap(data => {
        const result = {
          call: data.call,
          response: this.userService.getUserNameCount(data.val)
        };
        return of(result);
      })
    ).subscribe(res => {
      res.response.subscribe(result => {
        res.call({
          status: true,
          val: result
        });
      }, err => {
        res.call({
          status: false
        });
      });
    });
  }

  /**
   * 帐号校验
   */
  userNameAsyncValidator = (control: FormControl) => Observable.create((observer: Observer<ValidationErrors>) => {
    const accountReg = RegConstant.ACCOUNT;
    if (!accountReg.test(control.value)) {
      observer.next({error: true, correct: true});
      observer.complete();
    } else {
      this.accountText.next({
        val: control.value,
        call: (res) => {
          if (res.status) {
            if (res.val > 0 && control.value !== this.tempItem.account) {
              observer.next({error: true, duplicated: true});
            } else {
              observer.next(null);
            }
          } else {
            observer.next({error: true});
          }
          observer.complete();
        }
      });
    }
  })

  /**
   * 密码校验
   */
  passwordValidator = (control: FormControl): { [s: string]: boolean } => {
    if (!control.value) {
      return {required: true};
    }
    const passwordReg = RegConstant.PASSWORD;
    if (!passwordReg.test(control.value)) {
      return {error: true, correct: true};
    }
  }

  /**
   * 手机号校验
   */
  phoneValidator = (control: FormControl): { [s: string]: boolean } => {
    if (!control.value) {
      return {required: true};
    }
    const phoneReg = RegConstant.PHONE;
    if (!phoneReg.test(control.value)) {
      return {error: true, correct: true};
    }
  }

  /**
   * 邮箱校验
   */
  emailValidator = (control: FormControl): { [s: string]: boolean } => {
    if (control.value !== '' && control.value !== null) {
      const emailReg = RegConstant.EMAIL;
      if (!emailReg.test(control.value)) {
        return {error: true};
      }
    }
  }

  submit(): Observable<any> {
    return new Observable((sub) => {
      if (!this.valid()) {
        sub.error(null);
        return;
      }
      if (this.isCheck) {
        this.isCheck = false;
        // 修改账号信息
        if (this._id !== undefined) {
          let saveVal: User = {
            id: this._id,
            ...comparisonValue(this.validateForm.value, this.tempItem)
          };
          if (hasProperty(saveVal, 'status')) {
            Object.assign(saveVal, {
              status: saveVal.status ? 1 : 0
            });
            saveVal = {
              id: this._id,
              ...comparisonValue(saveVal, this.tempItem)
            };
          }
          if (hasProperty(saveVal, 'roles')) {
            Object.assign(saveVal, {
              roles: saveVal.roles.join(',')
            });
            saveVal = {
              id: this._id,
              ...comparisonValue(saveVal, this.tempItem)
            };
          }
          // 先判断是否更改密码
          if (hasProperty(saveVal, 'password') && saveVal.password !== this.tempItem.password) {
            // 调加密字符串方法
            if (!hasProperty(saveVal, 'account')) {
              Object.assign(saveVal, {
                account: this.tempItem.account
              });
            }
            this.userService.encriptPwd(saveVal).subscribe(res => {
              if (res) {
                saveVal.password = res;
                this.update(saveVal).subscribe(result => {
                  this.isCheck = true;
                  sub.next();
                }, err => {
                  this.isCheck = true;
                  sub.error();
                });
              }
              sub.next();
            }, err => {
              sub.error();
            });
          } else {
            this.update(saveVal).subscribe(res => {
              sub.next();
            }, err => {
              sub.error();
            });
          }
        } else {
          let saveVal = this.validateForm.value;
          saveVal = normObject(saveVal);
          if (hasProperty(saveVal, 'roles')) {
            Object.assign(saveVal, {
              roles: saveVal.roles.join(',')
            });
          }
          if (hasProperty(saveVal, 'birthday')) {
            Object.assign(saveVal, {
              birthday: saveVal.birthday.getTime()
            });
          }
          this.add(saveVal).subscribe(res => {
            sub.next();
          }, err => {
            sub.error();
          });
        }
      }
    });
  }

  cancel(): Observable<any> {
    return of('cancel');
  }

  getUser(id: number): void {
    this.userService.getUserById(id)
      .subscribe(res => {
        this.tempItem = res;
        if (res.birthday !== undefined) {
          res.birthday = new Date(res.birthday);
        }
        this.validateForm.patchValue(res);
        if (res.roles.length > 0) {
          const roles = this.validateForm.value.roles.split(',');
          this.validateForm.patchValue({
            roles: roles.map((w) => {
              return +w;
            })
          });
        }
      });
  }

  add(item: User): Observable<void> {
    return new Observable((sub) => {
      if (this.validateForm.value.loginTime === undefined) {
        this.validateForm.value.loginTime = new Date();
      }
      this.userService.addUser(item)
        .subscribe(res => {
          if (res) {
            this.message.success(this.i18nService.translate('modify.return.add_success'));
            sub.next();
          } else {
            this.message.error(this.i18nService.translate('modify.return.add_error'));
          }
          this.isCheck = true;
        }, err => {
          this.isCheck = true;
          sub.error();
        });
    });
  }

  update(item: User): Observable<void> {
    return new Observable((sub) => {
      this.userService.updateUser(item)
        .subscribe(response => {
          if (response) {
            this.message.success(this.i18nService.translate('modify.return.edit_success'));
            sub.next();
          } else {
            this.message.error(this.i18nService.translate('modify.return.eidt_error'));
            sub.error();
          }
          this.isCheck = true;
        }, err => {
          this.isCheck = true;
          sub.error();
        });
    });
  }

  getAllRoles(val?: string, pid?: number): void {
    this.roleService.getAllRoles(1, 99)
      .subscribe(res => {
        this.rolesOptions = res.records;
      });
  }

}
